昨天的題目是透過直接將執行流程改為我們事先設計好的後門。但如果我們沒有設置後門,其實在早期版本的 libc 中,仍然可以使用其他方式 leak 出 libc,並進一步將執行流程轉向 one_gadget 或是直接使用 system 開啟 shell。
在 libc 2.23 版本中,我們可以透過一些技巧來 leak 出 libc base,甚至進而控制執行流程。過程簡單來說就是:
malloc 一塊 unsorted bin 大小的記憶體空間。free 掉 unsorted bin 大小的空間時,該 chunk 與 top chunk 合併。free 掉 unsorted bin 大小的空間,再輸出該空間的內容,如此就能 leak 出 libc 的地址。malloc 一塊 fastbin 大小的 chunk,並修改它的 fd,將滿足條件的地址放進 fastbin。malloc 一塊相同大小的 chunk 並使用它。如果將它修改為 one_gadget,即可輕鬆拿到 shell。之所以會使用到 __malloc_hook,是因為它與這個過程的密切關聯。
__libc_malloc 在執行 malloc 時,會先檢查 __malloc_hook 是否為空。如果 __malloc_hook 不為空,則會在執行 malloc 前先調用它,初始化過程完成後,__malloc_hook 的值會變成 0。
因為在 fastbin 中分配 chunk 的過程中會檢查 size 是否允許,所以我們需要在 __malloc_hook 周圍找到一個允許的地址,並利用這個地址來偽造 chunk。
有時候,one_gadget 的條件可能無法滿足,導致無法成功開啟 shell。這時可以利用 malloc_hook 與 realloc_hook 相鄰的特性,將 malloc_hook 改為 _libc_realloc + 0x14,並將 realloc_hook 改為 one_gadget。這樣可以控制 malloc_hook 指向的位置,並避開 _libc_realloc 的部分指令,從而調整 one_gadget 所需的條件,最終成功開啟 shell。
今天介紹了在 libc 2.23 版本中利用 Use After Free 技巧來 leak 出 libc 地址,進而控制執行流程。透過操控 __malloc_hook 和 realloc_hook,我們可以在特定情況下達成開啟 shell 的目的,即便 one_gadget 的條件不完全滿足。這是一種常見的漏洞利用方式,能夠有效地繞過機制並取得程式控制權。